package com.rjj.wlqq.wx.tool;

import com.alibaba.fastjson.JSON;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author r
 * @date 2020/12/26 20:16
 * redis 工具类
 * 配置写到这里那么构造这里就有注入，但是String没有注入的，只能写死的所以写到外边了，RedisConfig
 */
public class RedisUtil
{

    private String keyPrefix;
    RedisTemplate<String, ?> redisTemplate;


    public RedisUtil(RedisTemplate<String, ?> redisTemplate, String keyPrefix)
    {
        this.redisTemplate = redisTemplate;
        this.keyPrefix = keyPrefix;
    }

    /**
     * 前缀
     *
     * @param key key
     */
    private String formatKey(String key)
    {
        if (keyPrefix != null && !"".equalsIgnoreCase(keyPrefix.trim()))
        {
            return keyPrefix + ":" + key;
        }
        return key;
    }

    public Set<String> keys(final String keyPrefix)
    {
        return redisTemplate.keys(formatKey(keyPrefix));
    }

    public boolean set(final String key, final Object value)
    {
        return set(key, JSON.toJSONString(value));
    }


    public boolean set(final String key, final Object value, long expire)
    {
        return set(key, JSON.toJSONString(value), expire);
    }


    public boolean set(final String key, final String value)
    {
        return set(key, value, -1);
    }


    public Boolean set(final String key, final String value, long expire)
    {
        return redisTemplate.execute(new RedisCallback<Boolean>()
        {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException
            {
                connection.openPipeline();
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                connection.set(serializer.serialize(formatKey(key)), serializer.serialize(value));
                if (expire > -1)
                {
                    connection.expire(serializer.serialize(formatKey(key)), expire);
                }
                connection.closePipeline();
                return true;
            }
        });
    }

    public String get(final String key)
    {
        return redisTemplate.execute(new RedisCallback<String>()
        {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException
            {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                byte[] value = connection.get(serializer.serialize(formatKey(key)));
                return serializer.deserialize(value);
            }
        });
    }

    public <T> T get(final String key, Class<T> clz)
    {
        return redisTemplate.execute(new RedisCallback<T>()
        {
            @Override
            public T doInRedis(RedisConnection connection) throws DataAccessException
            {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                byte[] value = connection.get(Objects.requireNonNull(serializer.serialize(formatKey(key))));
                if (value != null)
                {
                    String str = serializer.deserialize(value);
                    return JSON.parseObject(str, clz);
                }
                return null;
            }
        });
    }

    public Boolean expire(final String key, long expire)
    {
        return redisTemplate.expire(formatKey(key), expire, TimeUnit.SECONDS);
    }

    public Boolean remove(final String key)
    {
        return redisTemplate.execute(new RedisCallback<Boolean>()
        {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException
            {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                connection.del(serializer.serialize(formatKey(key)));
                return true;
            }
        });
    }

    public <T> boolean setList(String key, List<T> list)
    {
        String value = JSON.toJSONString(list);
        return set(key, value);
    }

    public <T> boolean setList(String key, List<T> list, long expire)
    {
        String value = JSON.toJSONString(list);
        return set(key, value, expire);
    }

    public <T> List<T> getList(String key, Class<T> clz)
    {
        String json = get(key);
        if (json != null)
        {
            return JSON.parseArray(json, clz);
        }
        return null;
    }

}

